package com.renu.jdependencyanalyser.utils;

import com.renu.jdependencyanalyser.asm.CustomClassVisitor;
import com.renu.jdependencyanalyser.model.ClassModel;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;

import java.io.IOException;

public class MyAsmUtil {
    public static void readClass(String classPath, ClassModel classModel) {
        byte[] bytes = new byte[0];
        try {
            bytes = MyFileUtil.convertFileToByteArray(classPath);
            ClassReader classReader = new ClassReader(bytes);
            ClassVisitor classVisitor = new CustomClassVisitor(classModel);
            classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     *
     * @param classSig
     * @param methodName
     * @param methodDescriptor
     * @return org.example.test.test.MyClass::\nvoid <init>(int)  参数和返回类型 jdk和项目中的类要简写
     */
    public static String convertToSignature(String classSig ,String methodName, String methodDescriptor) {
            // 解析方法描述符，获取参数类型和返回类型
            String returnTypeDescriptor = methodDescriptor.substring(methodDescriptor.lastIndexOf(')') + 1);
            String returnType = getTypeFromDescriptor(returnTypeDescriptor);

            String parametersDescriptor = methodDescriptor.substring(1, methodDescriptor.lastIndexOf(')'));
            String[] parameterTypes = getParameterTypesFromDescriptor(parametersDescriptor);

            // 获取方法的签名
            StringBuilder signatureBuilder = new StringBuilder();
            signatureBuilder.append(classSig).append("::\n");
            signatureBuilder.append(MyProjectUtil.replaceJDKAndProjectClsSig2SimpleSig(returnType)).append(" ");
            signatureBuilder.append(methodName).append("(");

            for (int i = 0; i < parameterTypes.length; i++) {
                if (i > 0) {
                    signatureBuilder.append(", ");
                }
                signatureBuilder.append(MyProjectUtil.replaceJDKAndProjectClsSig2SimpleSig(parameterTypes[i]));
            }

            signatureBuilder.append(")");

            return signatureBuilder.toString();
    }

    public static String getTypeFromDescriptor(String descriptor)  {
        String type = null;
        switch (descriptor) {
            case "Z":
                type += "boolean";
                break;
            case "B":
                type= "byte";
                break;
            case "C":
                type= "char";
                break;
            case "S":
                type = "short";
                break;
            case "I":
                type =  "int";
                break;
            case "J":
                type =  "long";
                break;
            case "F":
                type =  "float";
                break;
            case "D":
                type =  "double";
                break;
            case "V":
                type =  "void";
                break;
            default:
                type =  descriptor.replaceAll("/", ".").substring(descriptor.indexOf('L')+1).replace(";","");

        }
        if (descriptor.contains("[")){
            type += " []";
        }
        return type;
    }

    private static String[] getParameterTypesFromDescriptor(String parametersDescriptor)  {
        if (parametersDescriptor.isEmpty()) {
            return new String[0];
        }

        String[] parameterDescriptors = parametersDescriptor.split(";");
        String[] parameterTypes = new String[parameterDescriptors.length];

        for (int i = 0; i < parameterDescriptors.length; i++) {
            parameterTypes[i] = getTypeFromDescriptor(parameterDescriptors[i]);
        }

        return parameterTypes;
    }
    public static String getAccessModifiers(int access) {
        StringBuilder modifiers = new StringBuilder();

        if ((access & Opcodes.ACC_PUBLIC) != 0) {
            modifiers.append("public ");
        }

        if ((access & Opcodes.ACC_PRIVATE) != 0) {
            modifiers.append("private ");
        }

        if ((access & Opcodes.ACC_PROTECTED) != 0) {
            modifiers.append("protected ");
        }

        if ((access & Opcodes.ACC_STATIC) != 0) {
            modifiers.append("static ");
        }

        if ((access & Opcodes.ACC_FINAL) != 0) {
            modifiers.append("final ");
        }

        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
            modifiers.append("abstract ");
        }

        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
            modifiers.append("synchronized ");
        }

        if ((access & Opcodes.ACC_NATIVE) != 0) {
            modifiers.append("native ");
        }

        if ((access & Opcodes.ACC_STRICT) != 0) {
            modifiers.append("strictfp ");
        }

        // 其他访问修饰符的检查...

        return modifiers.toString().trim();
    }

}
